package org.jvm.nativemethod.methods.java.lang;

import org.jvm.nativemethod.NativeMethodRegister;
import org.jvm.rtda.Object;
import org.jvm.rtda.heap.Klass;
import org.jvm.rtda.heap.classLoader.KlassLoaderRegister;
import org.jvm.rtda.thread.Frame;

/**
 * @author 海燕
 * @date 2023/2/26
 */
public class ObjectNativeMethod extends NativeMethodRegister {

    private static String jlObject = "java/lang/Object";

    public static void init() {
        try {
            register(jlObject, "getClass", "()Ljava/lang/Class;", ObjectNativeMethod.class.getDeclaredMethod("getClass", Frame.class));
            register(jlObject, "hashCode", "()I", ObjectNativeMethod.class.getDeclaredMethod("hashCode", Frame.class));
            register(jlObject, "clone", "()Ljava/lang/Object;", ObjectNativeMethod.class.getDeclaredMethod("clone", Frame.class));
            register(jlObject, "notifyAll", "()V", ObjectNativeMethod.class.getDeclaredMethod("notifyAll", Frame.class));
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

    /**
     * java/lang/Object中获取类对象的方法
     *
     * @param frame
     */
    public static void getClass(Frame frame) {
        //拿到实例的引用
        Object thisRef = frame.getLocalVars().getRef(0);
        //获取类对象
        Object jClass = thisRef.getKlass().getjClass();
        frame.getOperandStack().pushRef(jClass);
    }

    public static void hashCode(Frame frame) {
        Object object = frame.getLocalVars().getRef(0);
        frame.getOperandStack().pushInt(object.hashCode());
    }

    public static void clone(Frame frame) {
        Object object = frame.getLocalVars().getRef(0);
        //必须实现java/lang/Cloneable接口才可以调用clone方法
        Klass cloneable = KlassLoaderRegister.getBootKlassLoader().loadKlass("java/lang/Cloneable");
        if (!object.getKlass().isImplements(cloneable)) {
            throw new RuntimeException("clone not support");
        }
        frame.getOperandStack().pushRef(object.clone());
    }

    public static void notifyAll(Frame frame) {
        //TODO
    }


}
